package com.bhp.bhphrserver.security;

import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;

import java.util.Collection;

/**
 * @ClassName BhpAccessDecisionManager
 * @Description 自定义授权管理器
 * @Author 包海鹏
 * @Date 2020/4/23 17:06
 * @Version 1.0
 **/
public class BhpAccessDecisionManager implements AccessDecisionManager {

    /**
     * 判断当前登录的用户是否具备当前请求URL所需要的角色信息
     * 不具备：抛出AccessDeniedException
     * 具备：无操作
     *
     * @param auth       认证对象：包含当前登录用户的信息
     * @param o          FilterInvocation拦截器对象：包含当前请求
     * @param collection 当前请求所需要的角色列表
     * @throws AccessDeniedException
     * @throws InsufficientAuthenticationException
     */
    @Override
    public void decide(Authentication auth, Object o, Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException {
        Collection<? extends GrantedAuthority> auths = auth.getAuthorities();
        for (ConfigAttribute configAttribute : collection) {
            if ("ROLE_LOGIN".equals(configAttribute.getAttribute()) && auth instanceof UsernamePasswordAuthenticationToken) {
                // 登录后即可访问并且已经登录
                return;
            }
            for (GrantedAuthority authority : auths) {
                if (configAttribute.getAttribute().equals(authority.getAuthority())) {
                    // 当前登录用户具有所需权限
                    return;
                }
            }
        }
        throw new AccessDeniedException("权限不足");
    }

    @Override
    public boolean supports(ConfigAttribute configAttribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}
